package com.tjtt.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

import com.secease.ThreeDes;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


public class ThreeDES {

	private static final String Algorithm = "DES"; // 定义 加密算法,可用

	// DES,DESede,Blowfish

	private static final String privatekey = "2008@tjtt.com";

	private static char[] hexChar = { '0', '1', '2', '3', '4', '5', '6', '7',
			'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	public String setMd5Key(String password) {
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		md5.update(password.getBytes());
		return toHexString(md5.digest());
	}

	private String toHexString(byte[] b) {
		StringBuilder sb = new StringBuilder(b.length * 2);
		for (int i = 0; i < b.length; i++) {
			sb.append(hexChar[(b[i] & 0xf0) >>> 4]);
			sb.append(hexChar[b[i] & 0x0f]);
		}
		return sb.toString();
	}

	public String readKey(String path) {
		File file = new File(path);
		InputStream in = null;
		String s = null;
		try {
			byte[] tempbytes = new byte[100];
			int byteread = 0;
			in = new FileInputStream(file);
			while ((byteread = in.read(tempbytes)) != -1) {
				s = new String(tempbytes, 0, byteread);
			}
			if (s == null || "".equals(s)) {
				return "0";
			} else {
				return s;
			}
		} catch (Exception el) {
			el.printStackTrace();
			return "0";
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException el) {
					el.printStackTrace();
					return "0";
					// el.printStackTrace();
				}
			}
		}
	}

	public Map ENCRYPT(String word) {
		Map map = new HashMap();
		Random random = new Random();
		Integer randNumber = random.nextInt();
		String re = getEncString(word, randNumber + "");
		re = stringToHexString(re);
		map.put("key", randNumber + "");
		map.put("re", re);
		return map;
	}

	public String DECRYPT(String word, String publickey) {
		word = hexToString(word);
		System.out.println(word + "   " + publickey);
		String re = getDesString(word, publickey);
		return re;
	}

	public Key getKey(String strKey) {
		Key kp;
		try {
			KeyGenerator _generator = KeyGenerator.getInstance(Algorithm);
			_generator.init(new SecureRandom(strKey.getBytes()));
			kp = _generator.generateKey();
			_generator = null;
		} catch (Exception e) {
			throw new RuntimeException("获取key失败. 原因: " + e);
		}
		return kp;
	}

	/**
	 * 加密String明文输入,String密文输出
	 */
	private String getEncString(String strMing, String stringKey) {
		byte[] byteMi = null;
		byte[] byteMing = null;
		String strMi = "";
		// String mi = "";
		BASE64Encoder base64en = new BASE64Encoder();
		try {
			byteMing = strMing.getBytes("UTF8");
			byteMi = this.getEncCode(byteMing, stringKey).getBytes();
			strMi = base64en.encode(byteMi);
		} catch (Exception e) {
			throw new RuntimeException(
					"Error initializing SqlMap class. Cause: " + e);
		} finally {
			base64en = null;
			byteMing = null;
			byteMi = null;
		}
		return strMi;
	}

	/**
	 * 解密 以String密文输入,String明文输出
	 * 
	 * @param strMi
	 * @return
	 */
	private String getDesString(String strMi, String stringKey) {
		BASE64Decoder base64De = new BASE64Decoder();
		byte[] byteMing = null;
		byte[] byteMi = null;
		String strMing = "";
		try {
			byteMi = base64De.decodeBuffer(strMi);
			byteMing = this.getDesCode(byteMi, stringKey);
		} catch (Exception e) {
			throw new RuntimeException(
					"Error initializing SqlMap class. Cause: " + e);
		} finally {
			base64De = null;
			byteMing = null;
			byteMi = null;
		}
		return strMing;
	}

	/**
	 * 加密以byte[]明文输入,byte[]密文输出
	 * 
	 * @param byteS
	 * @return
	 */
	private String getEncCode(byte[] byteS, String key) {
		byte[] byteFina = null;
		Cipher cipher;
		try {
			cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
//			cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
//	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("AES");
	        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
			IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
			cipher.init(Cipher.ENCRYPT_MODE, secretKey,iv);
			byteFina = cipher.doFinal(byteS);
		} catch (Exception e) {
			throw new RuntimeException("加密byte失败. Cause: " + e);
		} finally {
			cipher = null;
		}
//		return new sun.misc.BASE64Encoder().encode(byteFina);
		return new sun.misc.BASE64Encoder().encode(byteFina);
	}

	/**
	 * 解密以byte[]密文输入,以byte[]明文输出
	 * 
	 * @param byteD
	 * @return
	 */
	private byte[] getDesCode(byte[] byteD, String key) {
		Cipher cipher;
		byte[] byteFina = null;
		try {
			cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
//			cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
//	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("AES");
	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
	        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
			IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
			cipher.init(Cipher.DECRYPT_MODE, secretKey,iv);
			byteFina = cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(new String(byteD)));
//			byteFina = cipher.doFinal(byteD);
		} catch (Exception e) {
			throw new RuntimeException("解密byte失败. Cause: " + e);
		} finally {
			cipher = null;
		}
		return byteFina;
	}

	public String byteToHex(byte b) {
		int i = b & 0xFF;
		String s = Integer.toHexString(i);
		if (s.length() % 2 != 0) {
			// Pad with 0
			s = "0" + s;
		}
		return s;
	}

	/**
	 * * 将十六进制字符串转换成二进制数组 *
	 */
	public byte[] hexToByte(String c) {
		String strTemp[] = c.split(":");
		byte[] results = new byte[strTemp.length];
		for (int i = 0; i < strTemp.length; i++) {
			results[i] = (byte) (Integer.parseInt(strTemp[i].toLowerCase(), 16));
		}
		return results;
	}

	private String stringToHexString(String strPart) {
		String hexString = "";
		for (int i = 0; i < strPart.length(); i++) {
			int ch = (int) strPart.charAt(i);
			String strHex = Integer.toHexString(ch);
			hexString = hexString + strHex;
		}
		return hexString;
	}

	private String hexToString(String strPart) {
		byte[] baKeyword = new byte[strPart.length() / 2];
		for (int i = 0; i < baKeyword.length; i++) {
			try {
				baKeyword[i] = (byte) (0xff & Integer.parseInt(strPart
						.substring(i * 2, i * 2 + 2), 16));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		try {
			strPart = new String(baKeyword, "utf-8");// UTF-16le:Not
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return strPart;
	}

	/***************************************************************************
	 * des加解密
	 */
	static final int pc_1_cp[] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42,
			34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36 };

	// 28
	static final int pc_1_dp[] = { 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46,
			38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 };

	// 48
	static final int pc_2p[] = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
			23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55,
			30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29,
			32 };

	// 16
	static final int ls_countp[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
			2, 1 };

	// 64
	static final int iip_tab_p[] = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44,
			36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40,
			32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27,
			19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23,
			15, 7 };

	// 64
	static final int _iip_tab_p[] = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47,
			15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13,
			53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51,
			19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17,
			57, 25 };

	// 48
	static final int e_r_p[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10,
			11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21,
			22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 };

	// 32
	static final int local_PP[] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23,
			26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22,
			11, 4, 25 };

	// [8][4][16]
	static final int ccom_SSS_p[][][] = {
			{ { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
					{ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
					{ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
					{ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } },

			{ { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
					{ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
					{ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
					{ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } },

			{ { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
					{ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
					{ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
					{ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } },

			{ { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
					{ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
					{ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
					{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } }, /*
																				 * err
																				 * on
																				 */

			{ { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
					{ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, /*
																				 * err
																				 * on
																				 */
					{ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
					{ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } },

			{ { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
					{ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
					{ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
					{ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } },

			{ { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
					{ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
					{ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
					{ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } },

			{ { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
					{ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
					{ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
					{ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } } };

	byte[][] C = new byte[17][28];

	byte[][] D = new byte[17][28];

	byte[][] K = new byte[17][48];

	/*
	 * iu2b把int转换成byte
	 */
	private static byte iu2b(int input) {
		byte output1;
		output1 = (byte) (input & 0xff);
		return output1;
	}

	/*
	 * b2iu把byte按照不考虑正负号的原则的”升位”成int程序， 因为java没有unsigned运算
	 */
	private static int b2iu(byte b) {
		return b < 0 ? b & 0x7F + 128 : b;
	}

	/*
	 * byteHEX()，用来把一个byte类型的数转换成十六进制的ASCII表示，
	 * 因为java中的byte的toString无法实现这一点，我们又没有C语言中的 sprintf(outbuf,"%02X",ib)
	 */
	public static String byteHEX(byte ib) {
		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
				'B', 'C', 'D', 'E', 'F' };
		char[] ob = new char[2];
		ob[0] = Digit[(ib >>> 4) & 0X0F];
		ob[1] = Digit[ib & 0X0F];
		String s = new String(ob);
		return s;
	}

	/*
	 * desMemcpy是一个内部使用的byte数组的块拷贝函数， 从input的inpos开始把len长度的
	 * 字节拷贝到output的outpos位置开始
	 */
	private void desMemcpy(byte[] output, byte[] input, int outpos, int inpos,
			int len) {
		int i;
		for (i = 0; i < len; i++)
			output[outpos + i] = input[inpos + i];
	}

	private void Fexpand0(byte[] in, byte[] out) {
		int divide;
		int i, j;
		byte temp1;

		for (i = 0; i < 8; i++) {
			divide = 7;
			for (j = 0; j < 8; j++) {
				temp1 = in[i];
				out[8 * i + j] = iu2b((b2iu(temp1) >>> divide) & 1);
				divide--;
			}
		}
	}

	private void FLS(byte[] bits, byte[] buffer, int count) {
		int i, j;
		for (i = 0; i < 28; i++) {
			buffer[i] = bits[(i + count) % 28];
		}
	}

	private void Fson(byte[] cc, byte[] dd, byte[] kk) {
		int i, j;
		byte[] buffer = new byte[56];
		for (i = 0; i < 28; i++)
			buffer[i] = cc[i];

		for (i = 28; i < 56; i++)
			buffer[i] = dd[i - 28];

		for (i = 0; i < 48; i++)
			kk[i] = buffer[pc_2p[i] - 1];
	}

	private void Fsetkeystar(byte[] bits) {
		int i, j;

		for (i = 0; i < 28; i++)
			C[0][i] = bits[pc_1_cp[i] - 1];
		for (i = 0; i < 28; i++)
			D[0][i] = bits[pc_1_dp[i] - 1];
		for (j = 0; j < 16; j++) {
			FLS(C[j], C[j + 1], ls_countp[j]);
			FLS(D[j], D[j + 1], ls_countp[j]);
			Fson(C[j + 1], D[j + 1], K[j + 1]);
		}
	}

	private void Fiip(byte[] text, byte[] ll, byte[] rr) {
		int i, j;
		byte[] buffer = new byte[64];
		byte[] tmp = new byte[64];
		Fexpand0(text, buffer);

		for (i = 0; i < 32; i++)
			ll[i] = buffer[iip_tab_p[i] - 1];

		for (i = 0; i < 32; i++)
			rr[i] = buffer[iip_tab_p[i + 32] - 1];
	}

	private void Fs_box(byte[] aa, byte[] bb) {
		int i, j, k, m;
		int y, z;
		byte[] ss = new byte[8];
		m = 0;
		for (i = 0; i < 8; i++) {
			j = 6 * i;
			y = b2iu(aa[j]) * 2 + b2iu(aa[j + 5]);
			z = b2iu(aa[j + 1]) * 8 + b2iu(aa[j + 2]) * 4 + b2iu(aa[j + 3]) * 2
					+ b2iu(aa[j + 4]);
			ss[i] = iu2b(ccom_SSS_p[i][y][z]);
			y = 3;
			for (k = 0; k < 4; k++) {
				bb[m++] = iu2b((b2iu(ss[i]) >>> y) & 1);
				y--;
			}

		}
	}

	private void FF(int n, byte[] ll, byte[] rr, byte[] LL, byte[] RR) {
		int i, j;
		byte[] buffer = new byte[64], tmp = new byte[64];
		for (i = 0; i < 48; i++)
			buffer[i] = rr[e_r_p[i] - 1];
		for (i = 0; i < 48; i++)
			buffer[i] = iu2b((b2iu(buffer[i]) + b2iu(K[n][i])) & 1);

		Fs_box(buffer, tmp);

		for (i = 0; i < 32; i++)
			buffer[i] = tmp[local_PP[i] - 1];

		for (i = 0; i < 32; i++)
			RR[i] = iu2b((b2iu(buffer[i]) + b2iu(ll[i])) & 1);

		for (i = 0; i < 32; i++)
			LL[i] = rr[i];
	}

	private void _Fiip(byte[] text, byte[] ll, byte[] rr) {
		int i, j;
		byte[] tmp = new byte[64];
		for (i = 0; i < 32; i++)
			tmp[i] = ll[i];
		for (i = 32; i < 64; i++)
			tmp[i] = rr[i - 32];
		for (i = 0; i < 64; i++)
			text[i] = tmp[_iip_tab_p[i] - 1];
	}

	private void Fcompress016(byte[] out, byte[] in) {
		int times;
		int i, j;

		for (i = 0; i < 16; i++) {
			times = 3;
			in[i] = '0';
			for (j = 0; j < 4; j++) {
				in[i] = iu2b(b2iu(in[i]) + (b2iu(out[i * 16 + j]) << times));
				times--;
			}
		}
	}

	void Fcompress0(byte[] out, byte[] in) {
		int times;
		int i, j;

		for (i = 0; i < 8; i++) {
			times = 7;
			in[i] = 0;
			for (j = 0; j < 8; j++) {
				in[i] = iu2b(b2iu(in[i]) + (b2iu(out[i * 8 + j]) << times));
				times--;
			}
		}
	}

	private void Fencrypt0(byte[] text, byte[] mtext) {
		byte[] ll = new byte[64], rr = new byte[64], LL = new byte[64], RR = new byte[64];
		byte[] tmp = new byte[64];
		int i, j;
		Fiip(text, ll, rr);

		for (i = 1; i < 17; i++) {
			FF(i, ll, rr, LL, RR);
			for (j = 0; j < 32; j++) {
				ll[j] = LL[j];
				rr[j] = RR[j];
			}
		}

		_Fiip(tmp, rr, ll);

		Fcompress0(tmp, mtext);
	}

	private void FDES(byte[] key, byte[] text, byte[] mtext) {
		byte[] tmp = new byte[64];
		Fexpand0(key, tmp);
		Fsetkeystar(tmp);
		Fencrypt0(text, mtext);
	}

	/* 加密 */
	private int ENCRYPT(byte[] key, byte[] s, byte[] d, int len) {
		int i, j;
		byte[] cData = new byte[8];
		byte[] cEncryptData = new byte[8];
		for (i = 0; i < len; i += 8) {
			if ((i + 8) > len) {
				desMemcpy(cData, s, 0, i, len - i);
				for (j = len - i; j < 8; j++)
					cData[j] = 0;
			} else
				desMemcpy(cData, s, 0, i, 8);
			FDES(key, cData, cEncryptData);
			desMemcpy(d, cEncryptData, i, 0, 8);

		}
		return i;
	}

	private void Fdiscrypt0(byte[] mtext, byte[] text) {
		byte[] ll = new byte[64], rr = new byte[64], LL = new byte[64], RR = new byte[64];
		byte[] tmp = new byte[64];
		int i, j;
		Fiip(mtext, ll, rr);

		for (i = 16; i > 0; i--) {
			FF(i, ll, rr, LL, RR);
			for (j = 0; j < 32; j++) {
				ll[j] = LL[j];
				rr[j] = RR[j];
			}
		}

		_Fiip(tmp, rr, ll);

		Fcompress0(tmp, text);
	}

	/***************************************************************************
	 * function: DES parameter: u_char * key ; key for encrypt u_char * mtext ;
	 * encipher data u_char * text ; plain data return: none
	 **************************************************************************/
	private void _FDES(byte[] key, byte[] mtext, byte[] text) {
		byte[] tmp = new byte[64];
		Fexpand0(key, tmp);
		Fsetkeystar(tmp);
		Fdiscrypt0(mtext, text);
	}

	/* 解密 */
	private int DECRYPT(byte[] key, byte[] s, byte[] d, int len) {
		int i;
		byte[] cData = new byte[8];
		byte[] cEncryptData = new byte[8];
		for (i = 0; i < len; i += 8) {
			desMemcpy(cEncryptData, d, 0, i, 8);
			_FDES(key, cEncryptData, cData);
			desMemcpy(s, cData, i, 0, 8);
		}
		return i;
	}

	private byte[] hexStr2ByteArr(String strIn) {
		byte[] arrB = strIn.getBytes();
		int iLen = arrB.length;

		// 两个字符表示一个字节，所以字节数组长度是字符串长度除以2
		byte[] arrOut = new byte[iLen / 2];
		for (int i = 0; i < iLen; i = i + 2) {
			String strTmp = new String(arrB, i, 2);
			arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
		}
		return arrOut;
	}

	public String desENCRYPT(String key, String str) {
		int i1;
		byte[] byte2 = new byte[3000];
		byte[] byte1 = str.getBytes();
		String skey = key;
		i1 = ENCRYPT(skey.getBytes(), byte1, byte2, byte1.length);
		String digestHexStr = "";
		for (int i = 0; i < i1; i++) {
			digestHexStr += byteHEX(byte2[i]);
		}
		return digestHexStr;
	}

	public String desDECRYPT(String key, String str) {
		int i2;
		byte[] byteMingW = new byte[3000];
		byte[] byteMiW = new byte[3000];
		byteMiW = hexStr2ByteArr(str);
		String skey = key;
		i2 = DECRYPT(skey.getBytes(), byteMingW, byteMiW, byteMiW.length);
		return getLetter_num(new String(byteMingW, 0, i2));
	}

	/***************************************************************************
	 * end
	 */

	/***************************************************************************
	 * 过滤字符串中不是数字和字母的字符
	 */
	public String getLetter_num(String args) {
		char[] ch = args.toCharArray();
		char[] sh = new char[args.length()];
		int j = -1;
		for (int i = 0; i < ch.length; i++)

		{
			String c = args.substring(i, i + 1);
			if (c.endsWith("0") || c.endsWith("1") || c.endsWith("2")
					|| c.endsWith("3") || c.endsWith("4") || c.endsWith("5")
					|| c.endsWith("6") || c.endsWith("7") || c.endsWith("8")
					|| c.endsWith("9")) {
				j++;
				sh[j] = c.toCharArray()[0];
			} else if ((ch[i] >= 'A' && ch[i] <= 'Z')
					|| (ch[i] >= 'a' && ch[i] <= 'z')) {
				j++;
				sh[j] = ch[i];
			}
		}
		String results = new String(sh);
		String result = results.substring(0, j + 1);
		return result;
	}

	private String strDesENCRYPT(String key, String str) {
		int i1;
		byte[] byte2 = new byte[3000];
		byte[] byte1 = str.getBytes();
		String skey = key;
		i1 = ENCRYPT(skey.getBytes(), byte1, byte2, byte1.length);
		String digestHexStr = "";
		for (int i = 0; i < i1; i++) {
			digestHexStr += byteHEX(byte2[i]);
		}
		return digestHexStr;
	}

	private String strDesDECRYPT(String key, String str) {
		int i2;
		byte[] byteMingW = new byte[3000];
		byte[] byteMiW = new byte[3000];
		byteMiW = hexStr2ByteArr(str);
		String skey = key;
		i2 = DECRYPT(skey.getBytes(), byteMingW, byteMiW, byteMiW.length);
		return getLetter_num(new String(byteMingW, 0, i2));
	}

	public Map ENCRYPTDES(String username, String pwd, String keypath) {
		String keyStr = readKey(keypath);
		Map m = new HashMap();
		if ("0".equals(keyStr)) {
			m.put("status", keyStr);
			return m;
		} else {
			String key = privatekey + keyStr;
			String ename = strDesENCRYPT(key, username);
			String epwd = strDesENCRYPT(key, pwd);
			m.put("ename", ename);
			m.put("epwd", epwd);
			m.put("status", "1");
			return m;
		}
	}

	public Map DECRYPTDES(String username, String pwd, String keypath) {
		Map m = new HashMap();
		String keyStr = readKey(keypath);
		if ("0".equals(keyStr)) {
			m.put("status", keyStr);
			return m;
		} else {
			String key = privatekey + keyStr;
			String dname = strDesDECRYPT(key, username);
			String dpwd = strDesDECRYPT(key, pwd);
			m.put("dname", dname);
			m.put("dpwd", dpwd);
			m.put("status", "1");
			return m;
		}
	}

	/**
	 * 加密字符串
	 * 
	 * @param str
	 * @param keypath
	 * @return
	 */
	private String ENCRYPTDES(String str, String keypath) {
		String keyStr = readKey(keypath);
		Map m = new HashMap();
		if ("0".equals(keyStr)) {
			m.put("status", keyStr);
			return "0";
		} else {
			return strDesENCRYPT(privatekey + keyStr, str);
		}
	}

	public String DECRYPTDES(String str, String keypath) {
		Map m = new HashMap();
		String keyStr = readKey(keypath);
		if ("0".equals(keyStr)) {
			m.put("status", keyStr);
			return keyStr;
		} else {
			String key = privatekey + keyStr;
			String dname = strDesDECRYPT(key, str);
			m.put("dname", dname);
			return strDesDECRYPT(privatekey + keyStr, str);
		}
	}

	public Map getNamePwd(String hashnamepwd, String keypath) {
		Map m = new HashMap();
		try {
			BASE64Decoder base64de = new BASE64Decoder();
			byte[] b = base64de.decodeBuffer(hashnamepwd);
			String param = new String(b);
			String[] sf = param.split("&");
			String snn = sf[0];
			String snp = sf[1];
			m = DECRYPTDES(snn, snp, keypath);
			return m;
		} catch (IOException e) {
			m.put("status", "0");
			return m;
		}
	}

	public String setNamePwd(String name, String pwd, String keypath) {
		Map m = ENCRYPTDES(name, pwd, "c:\\key.dat");
		// Map m = ENCRYPTDES(name, pwd, Properties.getString("keypath"));
		if ("0".equals(m.get("status"))) {
			return "0";
		} else {
			String str = m.get("ename").toString() + "&"
					+ m.get("epwd").toString();
			BASE64Encoder base64en = new BASE64Encoder();
			String param = base64en.encode(str.getBytes());
			return param;
		}
	}

	/**
	 * 获得加密后base64字符串
	 * 
	 * @param pwd
	 * @param keypath
	 * @return
	 */
	public String setbase64(String pwd, String keypath) {
		String enStr = ENCRYPTDES(pwd, "c:\\key.dat");
		// System.out.println(Properties.getString());
		// String enStr = ENCRYPTDES(pwd, Properties.getString("keypath"));
		if ("0".equals(enStr)) {
			return "0";
		} else {
			// base64编码
			BASE64Encoder base64en = new BASE64Encoder();
			String param = base64en.encode(enStr.getBytes());
			return param;
		}
	}

	/**
	 * 获得解密后base64字符串
	 * 
	 * @param hashnamepwd
	 * @param keypath
	 * @return
	 */
	public String getbase64(String str, String keypath) {
		try {
			BASE64Decoder base64de = new BASE64Decoder();
			byte[] b = base64de.decodeBuffer(str);
			String param = new String(b);
			// System.out.println(Properties.getString());
			// return DECRYPTDES(param, Properties.getString("keypath"));
			return DECRYPTDES(param, "c:\\key.dat");
		} catch (IOException e) {
			e.printStackTrace();
			return "0";
		}
	}

	public static void main(String[] args) {
		File infile = new File("d:\\[小晓家园www.xxjy.org]潜伏01.rar");
		File outfile = new File("d:\\[小晓家园www.xxjy.org]潜伏010.rar");
//		File outfile1 = new File("c:\\TDDOWNLOAD2.rar");
		byte[] inb = new byte[1024];
		byte[] outb = new byte[1024];
		FileInputStream fin;
		FileOutputStream fout;
		ThreeDES td = new ThreeDES();
		BASE64Encoder b64e = new BASE64Encoder();
		BASE64Decoder b64d = new BASE64Decoder();
		try {
			long starttime = Calendar.getInstance().getTimeInMillis();
//			enoldCrByteFile("c:\\bsmain_runtime.log","c:\\bsmain_runtime1.log","11111111");
//			enoldCrByteFile1("c:\\bsmain_runtime.log","c:\\bsmain_runtime2.log","11111111");
			long endtime = Calendar.getInstance().getTimeInMillis();
			System.out.println("time:"+(endtime - starttime));
//			deoldCrByteFile("c:\\bsmain_runtime1.log","c:\\bsmain_runtime3.log","11111111");
			System.out.println("time:"+ (endtime - Calendar.getInstance().getTimeInMillis()));
			
//			try {
//				td.encrypt("c:\\sadf.pdb","c:\\sadf1.pdb",td.getKey("11111111"));
//				td.decrypt("c:\\sadf1.pdb","c:\\sadf2.pdb",td.getKey("11111111"));
//			} catch (Exception e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
			
			// fin = new FileInputStream(infile);
			// FileChannel ch = fin.getChannel();
			// MappedByteBuffer byteBuffer =
			// ch.map(FileChannel.MapMode.READ_ONLY, 0, infile.length());
//			MappedByteBuffer byteBuffer = new RandomAccessFile(
//					"c:\\TDDOWNLOAD.rar", "r").getChannel().map(
//					FileChannel.MapMode.READ_ONLY, 0, infile.length());
			fin = new FileInputStream(infile);
			fout = new FileOutputStream(outfile);
			fin.read(inb);
//			String outstr = b64e.encode(byteBuffer);
			fout.write(outb);
			fout.flush();
//			long endtime = Calendar.getInstance().getTimeInMillis();
//			System.out.println(endtime - starttime);
//
//			fin = new FileInputStream(outfile);
//			fout = new FileOutputStream(outfile1);
//			inb = new byte[(int) outfile.length()];
//			fin.read(inb);
//			outb = td.getDesCode(inb, td.getKey("12sd"));
//			outb = b64d.decodeBuffer(new String(outb));
//			fout.write(outb);
//			fout.flush();
//			System.out.println(starttime
//					- Calendar.getInstance().getTimeInMillis());

			// in = new FileInputStream(file);
			// FileChannel ch = in.getChannel();
			// MappedByteBuffer byteBuffer =
			// ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());

			// fin.read(inb, 0, inb.length);
			// fin.close();
			// byte[] outb = td.getDesCode(inb, td.getKey("12sd"));
			//			
			// fout = new FileOutputStream(outfile);
			// fout.write(outb);
			// fout.close();
			//			
			// fout = new FileOutputStream(outfile1);
			// outb = td.getEncCode(outb,td.getKey("12sd"));
			// fout.write(outb);
			// fout.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static boolean enoldCrByteFile(String file1, String file2, String key) {
		ThreeDES td = new ThreeDES();
		try {
			File file_in = new File(file1);
			File file_out = new File(file2);
			FileInputStream in = new FileInputStream(file_in);
			FileOutputStream out = new FileOutputStream(file_out);
			byte[] bytes = new byte[1024];
			// String end = "<!~!>";
			// System.out.print(end);
			// byte [] bend = end.getBytes();
			while ((in.read(bytes)) != -1) {
				byte[] bout = td.getEncCode(bytes, key).getBytes();
//				System.out.println(bytes.length);
				System.out.println(bout.length);
				out.write(bout, 0, bout.length);
				// out.write(bend,0,bend.length);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("File enCrypto Error!");
			return false;
		}
	}

	/**//*
		 * 解密文件 file1密文解密成file2明文 key只能是8个byte
		 */
	public static boolean deoldCrByteFile(String file1, String file2, String key) {
		ThreeDES td = new ThreeDES();
		try {
			File file_in = new File(file1);
			File file_out = new File(file2);
			FileInputStream in = new FileInputStream(file_in);
			FileOutputStream out = new FileOutputStream(file_out);
			byte[] bytes = new byte[1412];
			// String end = "<!~!>";
			// System.out.print(end);
			// byte [] bend = end.getBytes();
			while ((in.read(bytes)) != -1) {
				byte[] bout = td.getDesCode(bytes, key);
				out.write(bout, 0, bout.length);
				// out.write(bend,0,bend.length);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("File deCrypto Error!");
			return false;
		}
	}
	
	  /**
     * 把文件srcFile加密后存储为destFile
     *
     * @param srcFile
     * @param destFile
     */
    private void encrypt(String srcFile, String destFile, Key privateKey)
                    throws Exception {
    	SecureRandom sr = new SecureRandom();
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        IvParameterSpec spec=new IvParameterSpec(privateKey.getEncoded());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey,spec);
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        byte[] b = new byte[2048];
        while (fis.read(b) != -1) {
            fos.write(cipher.doFinal(b));
        }
        fos.close();
        fis.close();
    }

    /**
     * 把文件srcFile解密后存储为destFile
     *
     * @param srcFile
     * @param destFile
     * @param privateKey
     * @throws Exception
     */
    private void decrypt(String srcFile, String destFile, Key privateKey)
                    throws Exception {
//SecureRandom sr = new SecureRandom();
     Cipher ciphers = Cipher.getInstance("DES/CBC/PKCS5Padding");
     IvParameterSpec spec=new IvParameterSpec(privateKey.getEncoded());
     ciphers.init(Cipher.DECRYPT_MODE,privateKey,spec);
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);  
        byte[] b = new byte[2064];
        while (fis.read(b) != -1) {                 
            fos.write(ciphers.doFinal(b));
        }
        fos.close();
        fis.close();
    }
}
